package org.leo.study.common.utils;

import com.google.common.collect.Lists;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author
 * 创建时间 2017-07-05 16:54
 */
public class TreeUtil {


    public static <T> List<T> createTree(List<T> list, String keyFieldName, String parentKeyFieldName, String subFieldName) {
        List<T> reslt = new ArrayList<T>();

        for (int i = 0; i < list.size(); i++) {
            T node_1 = list.get(i);
            Boolean isRoot = true;
            for (int j = 0; j < list.size(); j++) {
                T node_2 = list.get(j);
                Object keyFieldValue = ReflectUtil.getValueByField(parentKeyFieldName, node_1);
                Object parentFieldValue = ReflectUtil.getValueByField(keyFieldName, node_2);
                if (keyFieldValue != null && keyFieldValue.equals(parentFieldValue)) {
                    isRoot = false;
                    break;
                }
            }
            if (isRoot) {
                createTree(list, node_1, keyFieldName, parentKeyFieldName, subFieldName);
                reslt.add(node_1);
            }
        }
        return reslt;
    }

    /**
     * @param list               树数据
     * @param root               根节点
     * @param keyFieldName       关联属性
     * @param parentKeyFieldName 关联父属性
     * @param subFieldName       子节点数据
     * @param <T>                根节点
     */
    public static <T> void createTree(List<T> list, T root, String keyFieldName, String parentKeyFieldName, String subFieldName) {
        Field keyField = ReflectUtil.getField(keyFieldName, root);
        Field parentKeyField = ReflectUtil.getField(parentKeyFieldName, root);
        Field subField = ReflectUtil.getField(subFieldName, root);
        find(list, root, keyField, parentKeyField, subField);
    }

    /**
     * 根据父节点的关联值 查找
     */
    public static <T, E> List<E> getKeys(List<T> list, T root, String keyFieldName, String parentKeyFieldName) {
        Field keyField = ReflectUtil.getField(keyFieldName, root);
        Field parentKeyField = ReflectUtil.getField(parentKeyFieldName, root);
        List<E> keys = Lists.newArrayList();
        E value = ReflectUtil.getValueByGetMethod(keyField, root);
        keys.add(value);
        findKeys(list, keys, root, keyField, parentKeyField);
        return keys;
    }

    private static <T> void find(List<T> list, T parent, Field keyField, Field parentKeyField, Field subField) {
        List<T> subs = getSubs(list, parent, keyField, parentKeyField);

        if (subs != null) {
            ReflectUtil.setValueByField(subField, parent, subs);
            for (T sub : subs) {
                //递归找子节点
                find(list, sub, keyField, parentKeyField, subField);
            }
        }
    }

    private static <T, E> List<E> findKeys(List<T> list, List<E> keys, T parent, Field keyField, Field parentKeyField) {
        List<T> subs = getSubs(list, parent, keyField, parentKeyField);

        List<E> subKeys = getSubKeys(list, parent, keyField, parentKeyField);
        if (subs != null) {
            keys.addAll(subKeys);
            for (T sub : subs) {
                //递归找子节点
                findKeys(list, keys, sub, keyField, parentKeyField);
            }
        }
        return keys;
    }


    private static <T> List<T> getSubs(List<T> list, T parent, Field keyField, Field parentKeyField) {
        List<T> subs = null;
        for (T t : list) {
            Object keyFieldValue = ReflectUtil.getValueByField(keyField, parent);
            Object parentFieldValue = ReflectUtil.getValueByField(parentKeyField, t);
            if (parentFieldValue != null && keyFieldValue.equals(parentFieldValue)) {
                if (subs == null) {
                    subs = Lists.newArrayList();
                }
                subs.add(t);
            }
        }
        return subs;
    }


    private static <T, E> List<E> getSubKeys(List<T> list, T parent, Field keyField, Field parentKeyField) {
        List<E> subs = null;
        for (T t : list) {
            Object keyFieldValue = ReflectUtil.getValueByField(keyField, parent); //父节点key
            Object parentFieldValue = ReflectUtil.getValueByField(parentKeyField, t); //根结点关联的key
            if (keyFieldValue.equals(parentFieldValue)) { //关联字段相等
                if (subs == null) {
                    subs = new ArrayList<>();
                }
                //取子节点key
                Object key = ReflectUtil.getValueByField(keyField, t);
                subs.add((E) key);
            }
        }
        return subs;
    }

    //例子
//    public static void main(String[] args) throws Exception {
//
//        NodeTreeResp nodeTreeResp = new NodeTreeResp();
//        nodeTreeResp.setCode("1000");
//        nodeTreeResp.setPcode(null);
//        nodeTreeResp.setValue("山东省");
//
//        NodeTreeResp nodeTreeResp2 = new NodeTreeResp();
//        nodeTreeResp2.setCode("1001");
//        nodeTreeResp2.setPcode("1000");
//        nodeTreeResp2.setValue("潍坊市");


//        NodeTreeResp nodeTreeResp3 = new NodeTreeResp();
//        nodeTreeResp3.setCode("1002");
//        nodeTreeResp3.setPcode("1000");
//        nodeTreeResp3.setValue("青岛市");
//
//        NodeTreeResp nodeTreeResp4 = new NodeTreeResp();
//        nodeTreeResp4.setCode("1003");
//        nodeTreeResp4.setPcode("1000");
//        nodeTreeResp4.setValue("高新区");
//
//        NodeTreeResp nodeTreeResp5 = new NodeTreeResp();
//        nodeTreeResp5.setCode("1004");
//        nodeTreeResp5.setPcode("1000");
//        nodeTreeResp5.setValue("四方区");
//
//        NodeTreeResp nodeTreeResp6 = new NodeTreeResp();
//        nodeTreeResp6.setCode("1005");
//        nodeTreeResp6.setPcode("1000");
//        nodeTreeResp6.setValue("清池街办");
//
//        NodeTreeResp nodeTreeResp7 = new NodeTreeResp();
//        nodeTreeResp7.setCode("1010");
//        nodeTreeResp7.setPcode("1002");
//        nodeTreeResp7.setValue("清池街办1");
//
//        NodeTreeResp nodeTreeResp8 = new NodeTreeResp();
//        nodeTreeResp8.setCode("1011");
//        nodeTreeResp8.setPcode("1002");
//        nodeTreeResp8.setValue("清池街办2");
//
//        NodeTreeResp nodeTreeResp9 = new NodeTreeResp();
//        nodeTreeResp9.setCode("1012");
//        nodeTreeResp9.setPcode("1002");
//        nodeTreeResp9.setValue("清池街办3");
//
//        NodeTreeResp nodeTreeResp10 = new NodeTreeResp();
//        nodeTreeResp10.setCode("1020");
//        nodeTreeResp10.setPcode("1010");
//        nodeTreeResp10.setValue("清池街办4");
//
//        NodeTreeResp nodeTreeResp11 = new NodeTreeResp();
//        nodeTreeResp11.setCode("0230");
//        nodeTreeResp11.setPcode(null);
//        nodeTreeResp11.setValue("重庆市");
//
//        NodeTreeResp nodeTreeResp12 = new NodeTreeResp();
//        nodeTreeResp12.setCode("0231");
//        nodeTreeResp12.setPcode("0230");
//        nodeTreeResp12.setValue("沙坪坝区");
//
//        NodeTreeResp nodeTreeResp13 = new NodeTreeResp();
//        nodeTreeResp13.setCode("0232");
//        nodeTreeResp13.setPcode("0230");
//        nodeTreeResp13.setValue("渝中区");
//
//        NodeTreeResp nodeTreeResp14 = new NodeTreeResp();
//        nodeTreeResp14.setCode("0233");
//        nodeTreeResp14.setPcode("0230");
//        nodeTreeResp14.setValue("南岸区");

//        List<NodeTreeResp> testTreeList = new ArrayList<>();
//        testTreeList.add(nodeTreeResp);
//        testTreeList.add(nodeTreeResp2);
//        testTreeList.add(nodeTreeResp3);
//        testTreeList.add(nodeTreeResp4);
//        testTreeList.add(nodeTreeResp5);
//        testTreeList.add(nodeTreeResp6);
//        testTreeList.add(nodeTreeResp7);
//        testTreeList.add(nodeTreeResp8);
//        testTreeList.add(nodeTreeResp9);
//        testTreeList.add(nodeTreeResp10);
//        testTreeList.add(nodeTreeResp11);
//        testTreeList.add(nodeTreeResp12);
//        testTreeList.add(nodeTreeResp13);
//        testTreeList.add(nodeTreeResp14);
//        List<NodeTreeResp> reslt = TreeUtil.createTree(testTreeList, "code", "pcode", "childList");
//
//        System.out.println(JSONObject.toJSONString(reslt)); //通过上边的createTree方法，根节点，即testTree4就是最全的最后的树结构。

//        Class clazz = nodeTreeResp6.getClass();
//
//        System.out.println(JSONObject.toJSONString(getKeys(testTreeList, nodeTreeResp3, "code", "pcode")));
//    }
}
